package net.towee.client.com.stuff.view;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.google.inject.Inject;

import net.towee.client.com.stuff.presenter.GroupRolesShowerPresenter.Display;
import net.towee.client.event.RoleOperation;
import net.towee.client.event.RoleOperationEvent;
import net.towee.client.event.RoleOperationEvent.HasRoleOperationHandlers;
import net.towee.client.event.RoleOperationEvent.RoleOperationHandler;
import net.towee.client.i18n.ToweeConstants;
import net.towee.client.resources.ClientResource;
import net.towee.client.widgets.ExtFlowPanel;
import net.towee.client.widgets.LeftTabsWidget;
import net.towee.client.widgets.ListItemWidget;
import net.towee.client.widgets.SheduledInputBox;
import net.towee.model.account.AccountPermission;
import net.towee.model.account.Role;
import net.towee.model.account.impl.RoleImpl;

public class GroupRolesShowerView extends FlowPanel implements Display, HasRoleOperationHandlers, ClickHandler {
	private class RoleEditor extends FlowPanel implements ClickHandler {
		private final HasText roleItem;
		private final Button createRole = new Button();
		private final CheckBox defaultBox = new CheckBox();
		private final SheduledInputBox roleNameBox = new SheduledInputBox();
		private final FlexTable table = new FlexTable();
		private Role role;
		
		private Map<AccountPermission, CheckBox> permBoxes = new HashMap<AccountPermission, CheckBox>();

		public RoleEditor(Role r, HasText rItem) {
			this.roleItem = rItem;
			this.role = r;
			
			if(defaultRole.equals(r))
				defaultBox.setValue(true);
			else
				defaultBox.setValue(false);
			
			// Create name field
			if(rItem != null)
				roleNameBox.setText(r.getName());
			
			defaultBox.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					if( defaultBox.getValue() )
						RoleOperationEvent.fire(GroupRolesShowerView.this, role, RoleOperation.Type.SET_DEFAULT);
				}
			});
			
			createNameTable();
			createDataForm();
			
			// Create permissions
			createPermissions();
			
			// Create button
			if(role == null) {
				createRole.setText(constants.create());
				createRole.setStyleName(resource.css().lobbyNextStepButton());
				add(createRole);
				createRole.addClickHandler(this);
			}	else {
				roleNameBox.addChangeHandler(new ChangeHandler(){
					@Override
					public void onChange(ChangeEvent event) {
						role.setName(roleNameBox.getText().trim());
						roleItem.setText(roleNameBox.getText().trim());						
					}
				});
			}
		}
		
		private void createNameTable() {
			FlexTable table = new FlexTable();
			FlexCellFormatter cellFormatter = table.getFlexCellFormatter();
			table.addStyleName( resource.css().dataForm() );
			table.setCellSpacing(6);		
			
			// Create table
			table.setWidget(0, 0, getRowName( constants.roleName(), ""));
			table.setWidget(0, 1, roleNameBox);
			cellFormatter.setWidth(0, 1, "100%");
			
			add(table);
		}

		private void createDataForm() {
			// Create table
			FlexCellFormatter cellFormatter = table.getFlexCellFormatter();
			table.addStyleName( resource.css().dataForm() );
			table.setCellSpacing(6);		
			
			// Create table
			table.setWidget(0, 0, getRowName( constants.isDefaultRole(), constants.isDefaultRoleInfo()));
			table.setWidget(0, 1, defaultBox);
			cellFormatter.setWidth(0, 1, "100%");
			
			add(table);
		}
		
		private FlowPanel getRowName(String name, String desc){
			FlowPanel row = new FlowPanel();
			
			ExtFlowPanel nameSpan = new ExtFlowPanel(name);
			ExtFlowPanel descSpan = new ExtFlowPanel(desc);

			nameSpan.getElement().setAttribute("row", "name");
			descSpan.getElement().setAttribute("row", "desc");
			
			row.add(nameSpan);
			row.add(descSpan);
			
			return row;
		}

		private void createPermissions() {	
			table.getFlexCellFormatter().setColSpan(1, 0, 2);
			Label permLabel = new Label( constants.permissions() );
			permLabel.setStyleName( resource.css().lobbyGroupCreatorPermLabel() );
			table.setWidget(1, 0, permLabel);
			int i = 2;
			
			for(final AccountPermission p : AccountPermission.values()) {
				final CheckBox box = new CheckBox();
				permBoxes.put(p, box);
				
				if(role != null) {
					if(role.hasPermissions(p) ) {
						box.setValue(true);
					}
					if(role.isOwner()) {
						box.setEnabled(false);
					}	else {
						box.addClickHandler(new ClickHandler(){
							@Override
							public void onClick(ClickEvent event) {
								if (box.getValue()) {
									role.addPermission(p);
								} else {
									role.removePremission(p);
								}								
							}
						});
					}
				}
				
				table.setWidget(i, 1, box);
				try {
					table.setWidget(i, 0, getRowName( constants.getString( p.toString() ), ""));
				} catch(Exception e) {
					table.setWidget(i, 0, getRowName( p.toString(), ""));
				} 
				
				i++;
			}
		}

		@Override
		public void onClick(ClickEvent event) {
			if (!roleNameBox.getText().trim().isEmpty()) {

				// Update or create role
				if (roleItem == null) {
					role = new RoleImpl((Random.nextDouble() + new Date().getTime()) + "", roleNameBox
							.getText().trim());
					
					showRole(role);
					RoleOperationEvent.fire(GroupRolesShowerView.this, role, RoleOperation.Type.ADD);
				} else {
					role.setName(roleNameBox.getText().trim());
					roleItem.setText(roleNameBox.getText().trim());
				}
				
				// Set default box
				if(defaultBox.getValue()) {
					defaultRole = role;
					RoleOperationEvent.fire(GroupRolesShowerView.this, role, RoleOperation.Type.SET_DEFAULT);
				}

				// Set permissions
				for (Entry<AccountPermission, CheckBox> e : permBoxes.entrySet()) {
					if (e.getValue().getValue()) {
						role.addPermission(e.getKey());
					} else {
						role.removePremission(e.getKey());
					}
				}

				// Remove editor
				removeFromParent();
			}
		}
	}
	
	private final ToweeConstants constants;
	private final ClientResource resource;
	
	private final LeftTabsWidget roles;
	private final FlowPanel roleEditor = new FlowPanel();
	private Role defaultRole;
	
	@Inject
	public GroupRolesShowerView(ToweeConstants constants, ClientResource resource){
		this.constants = constants;
		this.resource = resource;
		roles = new LeftTabsWidget( resource );
		
		this.setStyleName( resource.css().stuffRolesShower() );
		roles.getElement().setAttribute("roles", "");
		roleEditor.getElement().setAttribute("editor", "");
		
		add(roles);
		add(roleEditor);
	}
	
	@Override
	public void showRole(Role r) {
		ListItemWidget w = (ListItemWidget) roles.addTab(r.getName());
		w.setLayoutData( r );
		w.addClickHandler(this);
	}

	@Override
	public HasRoleOperationHandlers getRoleOperationHandlers() {
		return this;
	}

	@Override
	public HandlerRegistration addRoleOperationHandler(RoleOperationHandler handler) {
		return addHandler(handler, RoleOperationEvent.getType());
	}

	@Override
	public void setDefaultRole(Role defaultRole) {
		this.defaultRole = defaultRole;
	}

	@Override
	public void onClick(ClickEvent event) {
		Role r = (Role)((Widget)event.getSource()).getLayoutData();
		roleEditor.clear();
		roleEditor.add(new RoleEditor(r, (HasText)event.getSource()));
	}

}
